#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <sys/socket.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>

#define IP "192.168.50.193"
#define PORT 9090
// 用户信息结构体
typedef struct Register
{
    char account[128];      // 账号
    char name[128];         // 用户名
    char password[128];     // 密码
    char phone_number[128]; // 电话号码
} RG;
// 好友列表结构体
typedef struct Friend
{
    char name[128];
} FD;
// 加好友
typedef struct add_friend
{
    char friend_name[128];
    char self_name[128];
} ADD_FRI;

// 私聊
typedef struct singleChat
{
    char destName[128];
    char selfName[128];
    char text[700];
} SIG_CHAT;

typedef struct message_node // 想想成一艘大轮船，专门运送数据，且自带数据类型
{
    short type;     // 消息的类型：1.注册 2.登录 3.找回密码 4.添加好友...........
    char buf[1022]; // 定义一个足够大的仓库，存放各种消息的数据
} MSG;

typedef struct loginInfo
{
    char name[128];
    int fd;
} LOGIN_INFO;

typedef struct Delete_acc
{
    char account[128];
    char password[128];
} DA;
int fd = 0;                    // 全局套接字
struct sockaddr_in addr;       // 服务器地址
char loginUserName[128] = {0}; // 当前登录用户的名字

typedef struct friendBattle
{
    int player1_fd;
    int player2_fd;
    int target_number;
    int player1_guess;
    int player2_guess;
    int player1_score;
    int player2_score;
} FRIEND_BATTLE;

typedef struct challenge
{
    char challenger[128];
    char opponent[128];
} CHALLENGE;
unsigned int szIPToInt(char *pIP) // 把字符串IP转为网络字节序整数IP
{
    unsigned int ip;
    inet_pton(AF_INET, pIP, &ip); // 把字符串IP转成数字IP
    return ip;
}

char *intIPToStr(unsigned int ip) // 把网络字节序整数IP转为字符串IP
{
    char *szIP = malloc(16);
    inet_ntop(AF_INET, &ip, szIP, 16);
    printf("%s\n", szIP);
    return szIP;
}

struct sockaddr_in getAddr(char *pszIp, uint16_t port) // 输入IP和端口，返回一个地址结构体
{
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;               // IPV4地址族
    addr.sin_addr.s_addr = szIPToInt(pszIp); // IP地址
    addr.sin_port = htons(port);             // 端口号，要转成大端字节序
    return addr;
}

/* *******************************ui界面函数********************************* */
void Home_ui()
{
    printf("<-----------猜数字游戏对战平台-------------->\n");
    printf("1.注册\n");
    printf("2.登录\n");
    printf("3.忘记密码\n");
    printf("4.退出\n");
    printf("<-----------猜数字游戏对战平台-------------->\n");
}
void Player_ui()
{
    printf("<----------------玩家界面-------------------->\n");
    printf("1.添加好友\n");
    printf("2.开始游戏\n");
    printf("3.好友私聊\n");
    printf("4.世界频道\n");
    printf("5.删除好友\n");
    printf("6.账号安全\n");
    printf("7.查看个人信息\n");
    printf("8.退出\n");
    printf("<----------------玩家界面-------------------->\n");
}
void Account_sui()
{
    printf("<------------------账户安全界面-------------------->\n");
    printf("1.修改密码\n");
    printf("2.账号注销\n");
    printf("3.返回\n");
    printf("<------------------账户安全界面-------------------->\n");
}
/* *******************************ui界面函数********************************* */

void _register() // 注册
{
    printf("请输入账号、密码、用户名、电话号码\n");
    RG rn;
    scanf("%s%s%s%s", rn.account, rn.password, rn.name, rn.phone_number);
    MSG msg;
    msg.type = 1;
    memcpy(msg.buf, &rn, sizeof(rn));
    write(fd, &msg, sizeof(msg));
    // 等待服务器响应
    read(fd, &msg, sizeof(msg));
    if (strcmp(msg.buf, "注册成功") == 0)
    {
        printf("注册成功\n");
    }
    else
    {
        printf("注册失败\n");
    }
}

int Login() // 登录
{
    printf("请输入用户名和密码\n");
    RG rn;
    scanf("%s%s", rn.account, rn.password);
    MSG msg;
    msg.type = 2;
    memcpy(msg.buf, &rn, sizeof(rn));
    write(fd, &msg, sizeof(msg)); // 输入账号和密码发给服务器
    read(fd, &msg, sizeof(msg));  // 接收服务器发来的验证消息
    if (msg.type == 101)
    {
        printf("%s\n", msg.buf);
        strcpy(loginUserName, rn.account);
        return 1;
    }
    else if (msg.type == 102)
    {
        printf("%s\n", msg.buf);
        return 0;
    }
    return 0;
}

void FindPassword() // 找回密码
{
    printf("请输入你要找回的账号和注册所填写的手机号码\n");
    RG rn;
    scanf("%s%s", rn.account, rn.phone_number);
    MSG msg;
    msg.type = 3;
    memcpy(msg.buf, &rn, sizeof(rn));
    write(fd, &msg, sizeof(msg)); // 将输入的账号和手机号码发给服务器
    read(fd, &msg, sizeof(msg));  // 接收服务器发来的密码
    printf("您的密码是%s\n", msg.buf);
}

void Add_friend() // 添加朋友
{
    printf("请输入你要添加的好友\n");
    ADD_FRI af;
    strcpy(af.self_name, loginUserName); // 当前用户
    scanf("%s", af.friend_name);         // 要添加的好友
    MSG msg;
    msg.type = 4; // 添加好友类型
    memcpy(msg.buf, &af, sizeof(af));
    write(fd, &msg, sizeof(msg));
    // 等待服务器响应
    read(fd, &msg, sizeof(msg));
    if (msg.type == 401)
    {
        printf("%s\n", msg.buf);
    }
    else if (msg.type == 402)
    {
        printf("%s\n", msg.buf);
    }
}

void Delete_friend() // 删除好友
{
    printf("请输入你要删除的好友名字\n");
    ADD_FRI af;
    strcpy(af.self_name, loginUserName); // 当前用户
    scanf("%s", af.friend_name);         // 输入要删除的好友名字
    MSG msg;
    msg.type = 10;
    memcpy(msg.buf, &af, sizeof(af));
    write(fd, &msg, sizeof(msg));
    read(fd, &msg, sizeof(msg));
    if (msg.type == 201)
    {
        printf("%s\n", msg.buf);
    }
    else if (msg.type == 202)
    {
        printf("%s", msg.buf);
    }
}

void Delete_Account() // 账户注销
{
    printf("输入你的密码：");
    DA rn;
    strcpy(rn.account, loginUserName); // 当前用户
    scanf("%s", rn.password);
    MSG msg;
    msg.type = 12;
    memcpy(msg.buf, &rn, sizeof(rn));
    write(fd, &msg, sizeof(msg));
    read(fd, &msg, sizeof(msg));
    if (msg.type == 501)
    {
        printf("%s\n", msg.buf);
        exit(0);
    }
    else if (msg.type == 502)
    {
        printf("%s\n", msg.buf);
    }
}
void Change_Password() // 修改密码
{
    printf("输入你新的密码：");
    DA rn;
    strcpy(rn.account, loginUserName); // 当前用户
    scanf("%s", rn.password);
    MSG msg;
    msg.type = 11;
    memcpy(msg.buf, &rn, sizeof(rn));
    write(fd, &msg, sizeof(msg));

    read(fd, &msg, sizeof(msg));
    printf("%s\n", msg.buf);
    if (msg.type == 301)
    {
        printf("%s\n", msg.buf);
    }
    else if (msg.type == 302)
    {
        printf("%s\n", msg.buf);
    }
}
void Account_security() // 账号安全
{
    Account_sui();
    int sel = -1;
    printf("输入你的选择：");
    scanf("%d", &sel);
    switch (sel)
    {
    case 1:
        Change_Password();
        break;
    case 2:
        Delete_Account();
        break;
    case 3:
        return; // 返回上一级
    default:
        printf("输入的选择无效\n");
        break;
    }
}
void handleGame(int fd) // 游戏处理函数
{
    MSG msg;
    msg.type = 20;
    write(fd, &msg, sizeof(msg));
    read(fd, &msg, sizeof(msg));
    printf("%s\n", msg.buf);
    while (1)
    {
        printf("请输入你的猜测：");
        int guess;
        scanf("%d", &guess);
        if (guess < 1 || guess > 100)
        {
            printf("请输入一个1到100之间的数字\n");
            continue;
        }
        msg.type = 21;
        sprintf(msg.buf, "%d", guess);
        write(fd, &msg, sizeof(msg));
        read(fd, &msg, sizeof(msg));
        printf("%s\n", msg.buf);
        if (strcmp(msg.buf, "猜对了") == 0 || guess == -1)
        {
            break;
        }
    }
}
void *work(void *arg) // 线程接聊天收消息
{
    while (1)
    {
        MSG msg;
        int bytesRead = read(fd, &msg, sizeof(msg)); // 读取服务器发来的消息
        if (bytesRead <= 0)
        {
            // 处理错误或连接关闭
            printf("连接关闭或读取错误\n");
            pthread_exit(NULL);
        }
        else
        {
            if (msg.type == 5)
            {
                printf("收到群聊消息：%s\n", msg.buf);
            }
            else if (msg.type == 6)
            {
                SIG_CHAT *sc = (SIG_CHAT *)msg.buf;
                printf("收到%s发来的私聊消息：%s\n", sc->selfName, sc->text);
            }
        }
    }
    pthread_exit(NULL);
}
void singleChat() // 私聊
{

    SIG_CHAT sc;
    printf("输入好友名字: ");
    scanf("%s", sc.destName);
    strcpy(sc.selfName, loginUserName);
    pthread_t pt;
    if (pthread_create(&pt, NULL, work, NULL) != 0)
    {
        printf("线程创建失败\n");
        return;
    }
    while (1)
    {
        printf("请输入聊天内容：");
        scanf("%s", sc.text);
        if (strcmp(sc.text, "exit") == 0)
        {
            MSG exitmsg;
            exitmsg.type = 9; // 设置退出消息类型为9
            write(fd, &exitmsg, sizeof(exitmsg));
            pthread_cancel(pt); // 取消线程
            break;
        }
        MSG msg;
        msg.type = 6; // 设置私聊消息类型为6
        memcpy(msg.buf, &sc, sizeof(SIG_CHAT));

        write(fd, &msg, sizeof(MSG)); // 发送私聊消息
    }
}
void handleGroupChat() // 群聊
{
    printf("进入群聊模式，输入消息并按回车发送，输入exit退出群聊。\n");

    pthread_t pt;
    if (pthread_create(&pt, NULL, work, NULL) != 0)
    {
        printf("线程创建失败\n");
        return;
    }

    while (1)
    {
        MSG msg;
        printf("请输入你要发送的内容: ");
        scanf("%s", msg.buf);

        if (strcmp(msg.buf, "exit") == 0)
        {
            msg.type = 8; // 设置退出消息类型为8
            write(fd, &msg, sizeof(msg));
            pthread_cancel(pt); // 取消线程
            break;
        }
        else
        {
            msg.type = 5;                 // 设置群聊消息类型为5
            write(fd, &msg, sizeof(msg)); // 发送群聊消息
        }
    }
}
void PrintInfo()
{
    printf("正在查询，请稍等\n");
    MSG msg;
    msg.type = 7;
    strcpy(msg.buf, loginUserName);
    write(fd, &msg, sizeof(msg));
    // 读取服务器的响应消息
    if (read(fd, &msg, sizeof(msg)) > 0)
    {
        if (msg.type == 403)
        {
            printf("%s\n", msg.buf);
        }
        else if (msg.type == 404)
        {
            printf("%s\n", msg.buf);
        }
    }
}
int main(int argc, const char *argv[])
{
    addr = getAddr(IP, PORT);
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == connect(fd, (struct sockaddr *)&addr, sizeof(addr)))
    {
        printf("服务器连接失败\n");
        return 0;
    }
    while (1)
    {
        Home_ui();
        int sel = -1;
        printf("输入你的选择：");
        scanf("%d", &sel);
        getchar(); // 清空输入缓冲区
        switch (sel)
        {
        case 1:
            _register();
            break;
        case 2:
            if (1 == Login())
            {
                while (1)
                {
                    Player_ui();
                    int sel1 = -1;
                    printf("输入你的选择：");
                    scanf("%d", &sel1);
                    switch (sel1)
                    {
                    case 1:
                        Add_friend();
                        break;
                    case 2:
                        handleGame(fd);
                        break;
                    case 3:
                        singleChat();
                        break;
                    case 4:
                        handleGroupChat();
                        break;
                    case 5:
                        Delete_friend();
                        break;
                    case 6:
                        Account_security();
                        break;
                    case 7:
                        PrintInfo();
                        break;
                    case 8:
                        // 返回上一级菜单
                        goto outer_loop;
                        break;
                    default:
                        printf("无效的选择,请重新输入\n");
                        break;
                    }
                }
            }
            break;
        case 3:
            FindPassword();
            break;
        case 4:
            printf("程序结束\n");
            close(fd);
            exit(0); // 退出程序
            break;
        default:
            printf("无效的选择,请重新输入\n");
            break;
        }
    }
outer_loop:
    close(fd);
    return 0;
}